package com.theme.passport.service.theme.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.theme.common.mvc.utils.PageUtils;
import com.theme.common.mvc.utils.Query;
import com.theme.passport.dao.theme.WidgeDao;
import com.theme.passport.entity.theme.WidgeEntity;
import com.theme.passport.service.theme.WidgeService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


@Service("widgeService")
public class WidgeServiceImpl extends ServiceImpl<WidgeDao, WidgeEntity> implements WidgeService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String userId = (String) params.get("userId");
        String keyword = (String) params.get("key");
        String status = (String) params.get("status");
        String typeId = (String) params.get("typeId");
        String free = (String) params.get("free");
        String classifyId = (String) params.get("classifyId");
        boolean themeShow = (Boolean) params.get("themeShow");
        String all = (String) params.get("all");
        if (StringUtils.isBlank(all)){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name,id,user_id, theme_id, theme_name,widget_size,"+
                                    "type_id,type_name,image, preview, classify_id,classify_name, status, created, updated")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("name,widget_size")
            );
            return new PageUtils(page);
        }else if (all.equals("1")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name,id,user_id, theme_id, theme_name,widget_size,"+
                                    "type_id,type_name,image, preview, classify_id,classify_name, status, created, updated")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .isNull(!themeShow,"theme_id")
                            .isNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("name,widget_size")
            );
            return new PageUtils(page);
        }else if(all.equals("2")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name,id,user_id, theme_id, theme_name,widget_size,"+
                                    "type_id,type_name,image, preview, classify_id,classify_name, status, created, updated")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .isNull(!themeShow,"theme_id")
                            .isNotNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("name,widget_size")
            );
            return new PageUtils(page);
        }else {
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name,id,user_id, theme_id, theme_name,widget_size,"+
                                    "type_id,type_name,image, preview, classify_id,classify_name, status, created, updated")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("name,widget_size")
            );
            return new PageUtils(page);
        }
    }

    @Override
    public PageUtils queryPageBydistinctName(Map<String, Object> params) {
        String keyword = (String) params.get("key");
        String status = (String) params.get("status");
        String showStatus = (String) params.get("showStatus");
        String free = (String) params.get("free");
        String userId = (String) params.get("userId");
        String themeId = (String) params.get("themeId");
        String typeId = (String) params.get("typeId");
        String classifyId = (String) params.get("classifyId");
        boolean themeShow = (Boolean) params.get("themeShow");
        String all = (String) params.get("all");
        if (StringUtils.isBlank(all)){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select(" name")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(free),"show_status", showStatus)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else if (all.equals("1")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(free),"show_status", showStatus)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .isNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
            );
            return new PageUtils(page);
        }else if(all.equals("2")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(free),"show_status", showStatus)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .isNotNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
            );
            return new PageUtils(page);
        }else {
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(free),"free", free)
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(free),"show_status", showStatus)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
            );
            return new PageUtils(page);
        }

    }


    @Override
    public PageUtils queryPageBydistinctName2(Map<String, Object> params) {
        String keyword = (String) params.get("key");
        String status = (String) params.get("status");
        String userId = (String) params.get("userId");
        String themeId = (String) params.get("themeId");
        String typeId = (String) params.get("typeId");
        String classifyId = (String) params.get("classifyId");
        boolean themeShow = (Boolean) params.get("themeShow");
        String all = (String) params.get("all");
        if (StringUtils.isBlank(all)){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else if (all.equals("1")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .isNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else if(all.equals("2")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .isNotNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else {
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }

    }


    @Override
    public PageUtils queryPageBydistinctNameV2(Map<String, Object> params) {
        String keyword = (String) params.get("key");
        String status = (String) params.get("status");
        String userId = (String) params.get("userId");
        String themeId = (String) params.get("themeId");
        String typeId = (String) params.get("typeId");
        String classifyId = (String) params.get("classifyId");
        boolean themeShow = (Boolean) params.get("themeShow");
        String all = (String) params.get("all");
        if (StringUtils.isBlank(all)){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .eq("show_status", 1)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else if (all.equals("1")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq("show_status", 1)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .isNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else if(all.equals("2")){
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq("show_status", 1)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .isNotNull("theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }else {
            IPage<WidgeEntity> page = this.page(
                    new Query<WidgeEntity>().getPage(params),
                    new QueryWrapper<WidgeEntity>()
                            .select("distinct name")
                            .eq(StringUtils.isNotBlank(userId),"user_id", userId)
                            .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                            .eq("show_status", 1)
                            .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                            .eq(StringUtils.isNotBlank(themeId), "theme_id", themeId)
                            .isNull(!themeShow,"theme_id")
                            .in(StringUtils.isNotBlank(status), "status", status)
                            .like(StringUtils.isNotBlank(keyword), "name", keyword)
                            .orderByDesc("updated")
            );
            return new PageUtils(page);
        }

    }


    @Override
    public List<WidgeEntity> queryWidgeListByName(String name) {
        Wrapper<WidgeEntity> queryWrapper = new QueryWrapper<WidgeEntity>()
                .eq("name", name)
                .orderByDesc("widget_size");
        return this.baseMapper.selectList(queryWrapper);
    }


    @Override
    public List<WidgeEntity> queryWidgeListByNameV2(String name) {
        Wrapper<WidgeEntity> queryWrapper = new QueryWrapper<WidgeEntity>()
                .eq("name", name)
                .eq("show_status", 1)
                .orderByDesc("widget_size");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<WidgeEntity> queryWidgeListByNameAndUserId(String name, Long userId) {
        Wrapper<WidgeEntity> queryWrapper = new QueryWrapper<WidgeEntity>()
                .eq("name", name)
                .eq(userId != null,"user_id", userId)
                .orderByDesc("widget_size");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<WidgeEntity> queryWidgeList(Long themeId) {
        Wrapper<WidgeEntity> queryWrapper = new QueryWrapper<WidgeEntity>()
                .eq("theme_id", themeId)
                .orderByDesc("widget_size");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<WidgeEntity> queryListBydistinctNameByIds(Map<String, Object> params) {
        List<Long> ids  = (List<Long>) params.get("ids");
        Wrapper<WidgeEntity> queryWrapper = new QueryWrapper<WidgeEntity>()
                .select("distinct name")
                .in(ids != null && ids.size()>0, "id", ids);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public PageUtils queryPageBydistinctNameByIds(Map<String, Object> params) {
        String status = (String) params.get("status");
        List<Long> ids  = (List<Long>) params.get("ids");
        IPage<WidgeEntity> page = this.page(
                new Query<WidgeEntity>().getPage(params),
                new QueryWrapper<WidgeEntity>()
                        .select("distinct name")
                        .isNull("theme_id")
                        .in(ids != null && ids.size()>0, "id", ids)
                        .in(StringUtils.isNotBlank(status), "status", status)
        );
        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageBydistinctNameByIdsV2(Map<String, Object> params) {
        String status = (String) params.get("status");
        List<Long> ids  = (List<Long>) params.get("ids");
        IPage<WidgeEntity> page = this.page(
                new Query<WidgeEntity>().getPage(params),
                new QueryWrapper<WidgeEntity>()
                        .select("distinct name")
                        .isNull("theme_id")
                        .eq("show_status",1)
                        .in(ids != null && ids.size()>0, "id", ids)
                        .in(StringUtils.isNotBlank(status), "status", status)
        );
        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageByCreateAesc(Map<String, Object> params) {
        String keyword = (String) params.get("key");
        String status = (String) params.get("status");
        String showStatus = (String) params.get("showStatus");

        String nts = (String) params.get("nts");
        String typeId = (String) params.get("typeId");
        String classifyId = (String) params.get("classifyId");
        boolean themeShow = (Boolean) params.get("themeShow");
        IPage<WidgeEntity> page = this.page(
                new Query<WidgeEntity>().getPage(params),
                new QueryWrapper<WidgeEntity>()
                        .select("distinct name,id,user_id, theme_id, theme_name,widget_size,"+
                                "type_id,type_name,image, preview, classify_id,classify_name, status, created, updated")
                        .eq(StringUtils.isNotBlank(nts), "nts", nts)
                        .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                        .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                        .eq(StringUtils.isNotBlank(showStatus), "show_status", showStatus)
                        .isNull(!themeShow,"theme_id")
                        .in(StringUtils.isNotBlank(status), "status", status)
                        .like(StringUtils.isNotBlank(keyword), "name", keyword)
                        .orderByDesc("updated")
        );
        return new PageUtils(page);

    }

    @Override
    public PageUtils queryWidgeByIds(Map<String, Object> params, List<Long> widgeIds) {
        IPage<WidgeEntity> page = this.page(
                new Query<WidgeEntity>().getPage(params),
                new QueryWrapper<WidgeEntity>()
                        .in(widgeIds.size()>0,"id", widgeIds)
                        .orderByDesc("updated")
        );
        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageByDistinctName(Map<String, Object> params) {
        String keyword = (String) params.get("key");
        String status = (String) params.get("status");
        String typeId = (String) params.get("typeId");
        String classifyId = (String) params.get("classifyId");
        boolean themeShow = (Boolean) params.get("themeShow");

        IPage<WidgeEntity> page = this.page(
                new Query<WidgeEntity>().getPage(params),
                new QueryWrapper<WidgeEntity>()
                        //.select("distinct name")
                        //.select("distinct name,id,user_id, theme_id, theme_name,widget_size,"+
                        //        "type_id,type_name,image, preview, classify_id,classify_name, status, created, updated")
                        .eq(StringUtils.isNotBlank(typeId), "type_id", typeId)
                        .eq(StringUtils.isNotBlank(classifyId), "classify_id", classifyId)
                        .isNull(!themeShow,"theme_id")
                        .in(StringUtils.isNotBlank(status), "status", status)
                        .like(StringUtils.isNotBlank(keyword), "name", keyword)
                        .orderByDesc("created")
        );
        // 根据 属性name名称去重
        List<WidgeEntity> newWidgeList = new ArrayList<>();
        page.getRecords().stream().filter(distinctByKey(p -> p.getName()))  //filter保留true的值
                .forEach(newWidgeList::add);
        page.setRecords(newWidgeList);

        return new PageUtils(page);
    }

    /**
     * 首先我们定义一个谓词Predicate用来过滤，过滤的条件是distinctByKey。谓词返回ture元素保留，返回false元素被过滤掉。
     * 当然我们的需求是过滤掉重复元素。我们去重逻辑是通过map的putIfAbsent实现的。putIfAbsent方法添加键值对，如果map集合中没有该key对应的值，则直接添加，并返回null，如果已经存在对应的值，则依旧为原来的值。
     * 如果putIfAbsent返回null表示添加数据成功(不重复)，如果putIfAbsent返回value(value==null :false),则满足了distinctByKey谓词的条件元素被过滤掉。
     * 这种方法虽然看上去代码量增大了，但是distinctByKey谓词方法只需要被定义一次，就可以无限复用。
     */
    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        //putIfAbsent方法添加键值对，如果map集合中没有该key对应的值，则直接添加，并返回null，如果已经存在对应的值，则依旧为原来的值。
        //如果返回null表示添加数据成功(不重复)，不重复(null==null :TRUE)
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 上面的例子都是按某一个对象属性进行去重，如果我们想按照某几个元素进行去重，就需要对上面的三种方法进行改造。
     * 我只改造其中一个，另外几个改造的原理是一样的，就是把多个比较属性加起来，作为一个String属性进行比较。
     */
    void testRemove6() {
        List<WidgeEntity> playerList = new ArrayList<>();
        List<WidgeEntity> newList = playerList.stream().collect(Collectors
                .collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WidgeEntity::getName))),
                        ArrayList::new));

        newList.forEach(System.out::println);
    }

}